﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using Assist;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using YArchitech.Controls;
using YArchitech.Revit;
using YArchitech.Revit.RevitExtension;
using Transfer.Utils;

namespace Transfer.CrossDocument
{
	public class CrossDocCopyManager
	{
		public CrossDocCopyManager(ExternalCommandData cmdData)
		{
			this.m_Revit = cmdData;
			this.m_ElementSelector = new ElementSelector(this.m_Revit);
		}

		public Result Copy(ref string msg)
		{
			ViewType viewType = this.m_Revit.Application.ActiveUIDocument.ActiveView.ViewType;
			if (viewType != 1 && viewType != 2)
			{
				YJKMessageBox.Show("当前命令只支持楼层平面视图和天花板平面视图");
				return Autodesk.Revit.UI.Result.Cancelled;
			}
			Result result;
			try
			{
				if (!this.GetSourceDocument())
				{
					this.CloseSourceDocument();
					result = Autodesk.Revit.UI.Result.Failed;
				}
				else
				{
					this.m_ElementSelector.GetTransformElementsIdList(this.m_SourceDocument, false);
					Transform transform = null;
					if (!this.GetTransform(ref transform))
					{
						this.CloseSourceDocument();
						result = Autodesk.Revit.UI.Result.Failed;
					}
					else
					{
						AutoCopyEntitiesManager autoCopyEntitiesManager = new AutoCopyEntitiesManager(this.m_Revit);
						List<List<ElementId>> generalElements = new List<List<ElementId>>();
						this.m_ElementSelector.GetGeneralElementsIdList(ref generalElements);
						bool copyWindows = this.m_ElementSelector.FindCopyTypeByName("Windows") || this.m_ElementSelector.FindCopyTypeByName("窗");
						bool copyDoors = this.m_ElementSelector.FindCopyTypeByName("Doors") || this.m_ElementSelector.FindCopyTypeByName("门");
						bool copyOpenings = this.m_ElementSelector.FindCopyTypeByName("Rectangular Straight Wall Opening") || this.m_ElementSelector.FindCopyTypeByName("矩形直墙洞口") || this.m_ElementSelector.FindCopyTypeByName("Rectangular Arc Wall Opening") || this.m_ElementSelector.FindCopyTypeByName("矩形弧墙洞口");
						autoCopyEntitiesManager.Copy(this.m_SourceDocument, transform, generalElements, copyWindows, copyDoors, copyOpenings);
						ManualCopyEntitiesManager manualCopyEntitiesManager = new ManualCopyEntitiesManager(this.m_Revit, this.m_SourceDocument, transform);
						List<FamilyInstance> baseOnWallParasiticEntitiesList = null;
						List<FamilyInstance> baseOnCeilingParasticElements = null;
						List<FamilyInstance> baseOnSurfaceParasiticEntitiesList = null;
						List<Element> wiresList = null;
						this.m_ElementSelector.GetManualCopyEntitiesList(ref baseOnWallParasiticEntitiesList, ref baseOnCeilingParasticElements, ref baseOnSurfaceParasiticEntitiesList, ref wiresList);
						manualCopyEntitiesManager.Copy(baseOnWallParasiticEntitiesList, baseOnCeilingParasticElements, baseOnSurfaceParasiticEntitiesList, wiresList);
						this.CloseSourceDocument();
						result = Autodesk.Revit.UI.Result.Succeeded;
					}
				}
			}
			catch (Exception ex)
			{
				msg = ex.Message;
				this.CloseSourceDocument();
				result = Autodesk.Revit.UI.Result.Failed;
			}
			return result;
		}

		public bool SetOriginWithStandardRoom()
		{
			Document document = this.m_Revit.Application.ActiveUIDocument.Document;
			XYZ zero = XYZ.Zero;
			if (!this.PickPoint("指定标准间基点", ref zero))
			{
				return false;
			}
			Transaction transaction = new Transaction(document);
			transaction.Start("add extensible storage");
			double x = zero.X;
			double y = zero.Y;
			Plane plane = RevitVersionFuncs.CreatePlanByOriginAndBasis(XYZ.Zero, XYZ.BasisX, XYZ.BasisY);
			SketchPlane sketchPlane = document.CreatYJKSketchPlane(plane);
			double num = Common.MMToFeet(1000.0);
			XYZ startPoint = new XYZ(x - num, y - num, 0.0);
			XYZ endPoint = new XYZ(x + num, y + num, 0.0);
			Line line = YJKLineEx.YJKGetBound(startPoint, endPoint);
			ExtensibleStorageManager.WriteOriginExtensibleStorageToCurve(document.Create.NewModelCurve(line, sketchPlane), zero);
			XYZ startPoint2 = new XYZ(x - num, y + num, 0.0);
			XYZ endPoint2 = new XYZ(x + num, y - num, 0.0);
			Line line2 = YJKLineEx.YJKGetBound(startPoint2, endPoint2);
			ExtensibleStorageManager.WriteOriginExtensibleStorageToCurve(document.Create.NewModelCurve(line2, sketchPlane), zero);
			transaction.Commit();
			return true;
		}

		private void GetSourceDocumentOrigin()
		{
			this.m_SourceDocOrigin = XYZ.Zero;
			foreach (Element element in new FilteredElementCollector(this.m_SourceDocument).OfClass(typeof(CurveElement)).ToElements().ToList<Element>())
			{
				if (!(element.GetType() != typeof(ModelLine)))
				{
					ModelLine modelLine = element as ModelLine;
					if (ExtensibleStorageManager.IsOriginMarkCurve(modelLine))
					{
						ExtensibleStorageManager.ReadOriginExtensibleStorageFromCurve(modelLine, ref this.m_SourceDocOrigin);
					}
				}
			}
		}

		private bool GetTransform(ref Transform transform)
		{
			transform = Transform.Identity;
			XYZ xyz = null;
			if (!this.PickPoint("选择定位基点", ref xyz))
			{
				return false;
			}
			XYZ xyz2 = xyz - this.m_SourceDocOrigin;
			double elevation = this.m_Revit.Application.ActiveUIDocument.ActiveView.GenLevel.Elevation;
			Transform transform2 = RevitVersionFuncs.CreateTranslation(new XYZ(xyz2.X, xyz2.Y, elevation));
			Transform transform3 = RevitVersionFuncs.CreateRotationAtPoint(XYZ.BasisZ, this.m_Rotate, xyz);
			if (this.m_Mirrered)
			{
				XYZ zero = XYZ.Zero;
				XYZ zero2 = XYZ.Zero;
				if (!this.PickPoint("选择镜像线起点", ref zero))
				{
					return false;
				}
				if (!this.PickPoint("选择镜像线终点", ref zero2))
				{
					return false;
				}
				XYZ basisX = (zero2 - zero).Normalize();
				Transform transform4 = RevitVersionFuncs.CreateReflection(RevitVersionFuncs.CreatePlanByOriginAndBasis(zero, basisX, XYZ.BasisZ));
				transform = transform.Multiply(transform4);
			}
			transform = transform.Multiply(transform3);
			transform = transform.Multiply(transform2);
			return true;
		}

		private bool GetSourceDocument()
		{
			CrossDocCopyForm crossDocCopyForm = new CrossDocCopyForm(this.m_Revit.Application, this.m_ElementSelector);
			DialogResult dialogResult = DialogResult.Cancel;
			while (crossDocCopyForm.ShowDialog() == DialogResult.OK)
			{
				if (!crossDocCopyForm.SettingAngle)
				{
					dialogResult = DialogResult.OK;
					break;
				}
				dialogResult = DialogResult.Cancel;
				double angle = 0.0;
				if (this.SelectAngle(ref angle))
				{
					crossDocCopyForm.Angle = angle;
					crossDocCopyForm.SaveData();
				}
			}
			if (dialogResult == DialogResult.Cancel)
			{
				return false;
			}
			this.m_Rotate = crossDocCopyForm.Angle;
			this.m_Mirrered = crossDocCopyForm.Mirror;
			string sourceFileName = crossDocCopyForm.GetSourceFileName();
			if (sourceFileName.ToUpper().IndexOf(".RVT") == -1)
			{
				YJKMessageBox.Show("不是标准的RVT文件");
				return false;
			}
			this.m_SourceDocument = this.m_Revit.Application.Application.OpenDocumentFile(sourceFileName);
			if (this.m_SourceDocument == null)
			{
				return false;
			}
			this.GetSourceDocumentOrigin();
			return true;
		}

		private bool SelectAngle(ref double angle)
		{
			XYZ ptCenter = null;
			XYZ ptOut = null;
			XYZ ptOut2 = null;
			if (!this.PickPoint("选择旋转中心点", ref ptCenter))
			{
				return false;
			}
			if (!this.PickPoint("选择旋转（逆时针方向）起始点", ref ptOut))
			{
				return false;
			}
			if (!this.PickPoint("选择旋转（逆时针方向）终止点", ref ptOut2))
			{
				return false;
			}
			try
			{
				double angle2 = Geometry.getAngle(ptCenter, ptOut);
				double angle3 = Geometry.getAngle(ptCenter, ptOut2);
				angle = Geometry.BetweenTheAngles(angle2, angle3, true);
			}
			catch (Exception)
			{
				angle = 0.0;
				return true;
			}
			return true;
		}

		private bool PickPoint(string statusPrompt, ref XYZ point)
		{
			try
			{
				XYZ xyz = this.m_Revit.Application.ActiveUIDocument.Selection.PickPoint(statusPrompt);
				point = new XYZ(xyz.X, xyz.Y, 0.0);
			}
			catch (Exception)
			{
				return false;
			}
			return true;
		}

		private void CloseSourceDocument()
		{
			if (this.m_SourceDocument != null)
			{
				this.m_SourceDocument.Close(false);
			}
		}

		private ExternalCommandData m_Revit;

		private Document m_SourceDocument;

		private ElementSelector m_ElementSelector;

		private XYZ m_SourceDocOrigin;

		private double m_Rotate;

		private bool m_Mirrered;
	}
}
